package votenaweb;

import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashSet;

import models.Casa;
import models.Materia;
import models.Politico;
import models.Posicao;
import models.Posicao.Voto;

import org.htmlcleaner.CleanerProperties;
import org.htmlcleaner.HtmlCleaner;
import org.htmlcleaner.TagNode;
import org.htmlcleaner.XPatherException;

public class VoteNaWebParser {
	// example XPATH queries in the form of strings - will be used later
    
    private static final String TITULO_XPATH = "//div/div[4]/div[4]/ul/li/div/div/div[2]/h3/a";
    private static final String AUTOR_XPATH = "//div[@class='span-7 prepend-1']/p[2]";
    private static final String DESCRICAO_XPATH = "//p[@class='summary']/a";
    private static final String DATAVOTACAO_XPATH = "//div[@class='span-7 prepend-1']/p[4]";
    // private static final String VOTO_XPATH = "//div/div[2]/div/span/img";
    private static final String VOTOPOVO_XPATH = "//div/div[@class='clearfix vote-graph user-vote-graph']";
    private static final String VOTO_SUB_XPATH = "//div/span/img";
    
	
    private static final Casa senado = Casa.find("byNome", "Senado").first();
    
	public static Collection<Materia> load(Politico politico) throws IOException, XPatherException {
		Collection<Materia> ret = new ArrayList<Materia>();
		
		// the URL whose HTML I want to retrieve and parse
        String option_url = "http://www.votenaweb.com.br/politicos/" + politico.getVoteNaWebId() + "/projetos_votados";

        // this is where the HtmlCleaner comes in, I initialize it here
        HtmlCleaner cleaner = new HtmlCleaner();
        CleanerProperties props = cleaner.getProperties();
        props.setAllowHtmlInsideAttributes(true);
        props.setAllowMultiWordAttributes(true);
        props.setRecognizeUnicodeChars(true);
        props.setOmitComments(true);

        // open a connection to the desired URL
        URL url = new URL(option_url);
        URLConnection conn = url.openConnection();

        //use the cleaner to "clean" the HTML and return it as a TagNode object
        TagNode node = cleaner.clean(new InputStreamReader(conn.getInputStream()));

        // once the HTML is cleaned, then you can run your XPATH expressions on the node, which will then return an array of TagNode objects (these are returned as Objects but get casted below)
        Object[] titulo_nodes = node.evaluateXPath(TITULO_XPATH);
        Object[] autor_nodes = node.evaluateXPath(AUTOR_XPATH);
        Object[] descricao_nodes = node.evaluateXPath(DESCRICAO_XPATH);
        Object[] datavotacao_nodes = node.evaluateXPath(DATAVOTACAO_XPATH);
        Object[] votopovo_nodes = node.evaluateXPath(VOTOPOVO_XPATH);

        int numeroEntradas = Math.min(titulo_nodes.length, autor_nodes.length);
        numeroEntradas = Math.min(numeroEntradas, descricao_nodes.length);
        numeroEntradas = Math.min(numeroEntradas, datavotacao_nodes.length);
        numeroEntradas = Math.min(numeroEntradas, votopovo_nodes.length);
       
        ArrayList<Object> votoArray = new ArrayList<Object>();// node.evaluateXPath(VOTO_XPATH);

        for (Object o : votopovo_nodes) {
    		Object[] votoPolitico = ((TagNode) o).getParent().getParent().evaluateXPath(VOTO_SUB_XPATH);
    		
    		if (votoPolitico.length == 0) {
    			votoArray.add(null);
    		} else {
    			votoArray.add(votoPolitico[0]);
    		}
    	}
        
        for (int i = 0; i < numeroEntradas; i++) {
        	TagNode tituloNode = (TagNode) titulo_nodes[i];
        	TagNode autorNode = (TagNode) autor_nodes[i];
        	TagNode descricaoNode = (TagNode) descricao_nodes[i];
        	TagNode dataVotacaoNode = (TagNode) datavotacao_nodes[i];
        	TagNode votoNode = (TagNode) votoArray.get(i);
        	
        	String titulo = tituloNode.getChildren().iterator().next().toString().trim();
        	String descricao = descricaoNode.getChildren().iterator().next().toString().trim();
        	String dataVotacao = dataVotacaoNode.getText().toString().replace("Data de votação no congresso: ", "");
        	
        	String autor = null;
        	
        	if (autorNode.getChildren().size() > 1) {
        		autor = ((TagNode) autorNode.getChildren().get(1)).getChildren().iterator().next().toString().trim();
        	} else {
        		autor = "Desconhecido";
        	}

        	String voto = null;
        	
        	if (votoNode != null) {
        		voto = votoNode.getAttributeByName("class");
        	}
        	
        	Politico entidadeAutor = Politico.find("byNome", autor).first(); 
        	
        	Materia m = Materia.find("byTitulo", titulo).first();
        	
        	if (m == null) {
        		m = new Materia();
        		m.setCasa(senado);
        		m.setAutor(entidadeAutor);
        		m.setDataVotacao(null);

        		if (! dataVotacao.equals("Indefinido")) {
        			SimpleDateFormat formatter = new SimpleDateFormat("dd/MM/yyyy");
        			
        			try {
						m.setDataVotacao((Date) formatter.parse(dataVotacao));
					} catch (ParseException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}        			
        		}
        		
        		m.setDescricao(descricao);
        		m.setTitulo(titulo);
        		m.setPosicoes(new HashSet<Posicao>());
        	}
        	
        	Posicao p = new Posicao();
    		p.setMateria(m);
    		p.setPolitico(politico);
    		p.setVoto(voto != null ? (voto.contains("yes") ? Voto.SIM : Voto.NAO) : Voto.NDA);
    		
        	m.getPosicoes().add(p);
        	
        	ret.add(m);
        }
        
        return ret;
	}
}
